package com.bw.skinfilecreator.utils;


import com.bw.skinfilecreator.bean.ProjectConfigEntity;
import com.bw.skinfilecreator.bean.UtilConfigEntity;
import com.google.gson.Gson;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Objects;

public class XxSKinUtil {
    public static final int TYPE_OPEN_EXPLORE = 2;
    public static final int TYPE_PUSH_TO_DEVICE = TYPE_OPEN_EXPLORE << 1;
    public static final int TYPE_REPLACE_TO_GIT = TYPE_OPEN_EXPLORE << 2;
    private final UtilConfigProvider utilConfigProvider;

    public XxSKinUtil(UtilConfigProvider utilConfigProvider) {
        this.utilConfigProvider = utilConfigProvider;
        saveConfig();
    }

    /**
     * 获取缓存目录路径
     */
    public static String getCacheDirPath() {
        String appName = "com.bw.skinfilecreator";
        String os = System.getProperty("os.name").toLowerCase();
        String home = System.getProperty("user.home");
        File dataDir;

        if (os.contains("win")) {
            // Windows系统: C:\Users\<用户名>\AppData\Roaming\<应用名>
            String appData = System.getenv("APPDATA");
            dataDir = new File(appData, appName);
        } else {
            // 默认使用用户主目录下的应用目录
            dataDir = new File(home, "." + appName);
        }

        // 确保目录存在
        if (!dataDir.exists()) {
            dataDir.mkdirs();
        }

        return dataDir.getAbsolutePath();
    }

    /**
     * 获取项目缓存所在目录
     *
     * @return
     */
    public static String getUtilCachePath() {
        return getCacheDirPath() + "\\util_cache";
    }

    /**
     * 获取项目缓存所在目录
     *
     * @return
     */
    public static String getProjectCachePath() {
        return getCacheDirPath() + "\\project_cache";
    }

    /**
     * 获取皮肤工程缓存目录
     *
     * @return
     */
    public static String getSkinProjectCachePath() {
        return getCacheDirPath() + "\\SkinFactory";
    }

    private void saveConfig() {
        UtilConfigEntity utilConfigEntity = new UtilConfigEntity();
        utilConfigEntity.setProjectConfigEntity(getUtilConfigProvider().getProject());
        utilConfigEntity.setSkinProjectPath(getUtilConfigProvider().getSkinProjectPath());
        //功能选项
        utilConfigEntity.setNeedOpenExplore((getUtilConfigProvider().launchType() & TYPE_OPEN_EXPLORE) != 0);
        utilConfigEntity.setNeedPushToDevice((getUtilConfigProvider().launchType() & TYPE_PUSH_TO_DEVICE) != 0);
        utilConfigEntity.setNeedPushToGit((getUtilConfigProvider().launchType() & TYPE_REPLACE_TO_GIT) != 0);

        //保存数据到本地
        File file = new File(getUtilCachePath());
        FileUtils.createFileByDeleteOldFile(file);
        try {
            PrintWriter printWriter = new PrintWriter(file);
            printWriter.print(new Gson().toJson(utilConfigEntity));
            printWriter.close();
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        }

        // 在主类（继承自Application的类）或控制器中使用

    }

    public void launch(boolean runAfterTask) {
        //准备工作
        try {
            getUtilConfigProvider().onLoadingStart();
            boolean result = onBeforeMakeSkin();
            getUtilConfigProvider().onLoadingEnd();
            if (!result) {
                getUtilConfigProvider().onLoadingEnd();
                return;
            }
            //打包
            getUtilConfigProvider().onLoadingStart();
            boolean makeSkinResult = makeSkin();
            getUtilConfigProvider().onLoadingEnd();
            if (!makeSkinResult) {
                return;
            }
            if (runAfterTask) {
                //处理打包资源
                onAfterMakeSkin();
            }

        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 制作皮肤包
     */
    private boolean makeSkin() {
        try {
            getUtilConfigProvider().onLog("------开始制作基础皮肤包------");
            String command = getUtilConfigProvider().getSkinProjectPath() + "\\assembleRelease.cmd"; // 要执行的命令
            Process process = Runtime.getRuntime().exec(command); // 执行命令
            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); // 获取命令输出流
            String line;
            ArrayList<String> content = new ArrayList<>();
            while ((line = reader.readLine()) != null) { // 逐行读取输出结果
                content.add(line);
                getUtilConfigProvider().onLog(line);
            }
            reader.close();
            int exitCode = process.waitFor(); // 等待命令执行完成并获取退出码
            if (exitCode == 1) return false;

            //修改名称
            String outFileDir = getUtilConfigProvider().getSkinProjectPath() + "\\app\\build\\outputs\\apk\\release\\";
            //找到目录下第一个文件
            File dir = new File(outFileDir);
            File file = Objects.requireNonNull(dir.listFiles())[0];
            //修改名称
            String skinFileName = getUtilConfigProvider().getProject().getSkinFileName();
            //重命名
            FileUtils.rename(file, skinFileName);
            getUtilConfigProvider().onLog("修改皮肤包名称为 " + skinFileName);

            getUtilConfigProvider().onLog("------制作基础皮肤包" + (exitCode == 0 ? "完成" : "失败") + "------");
            if (exitCode == 0) {
                getUtilConfigProvider().onCreateSkinFileSuccess();
            }
            return true;

        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        return false;
    }

    /**
     * 制作皮肤包之前的准备工作
     */
    private boolean onBeforeMakeSkin() throws IOException {
        getUtilConfigProvider().onLog("------资源准备阶段开始------");

        //如果缺少gradle目录,则重新解压
        File gradleFile = new File(getUtilConfigProvider().getSkinProjectPath() + "\\gradle");
        if (!gradleFile.exists()) {
            //删除旧的目录
            FileUtils.delete(getUtilConfigProvider().getSkinProjectPath());
            new CompressedResourceUtils().extractZipResource("/assets/SkinFactory.zip", getCacheDirPath(), msg -> getUtilConfigProvider().onLog(msg));
        }

        String originResPath = getUtilConfigProvider().getProject().getSourceProjectPath();
        String skinResPath = getUtilConfigProvider().getSkinProjectPath() + "\\app\\src\\main";
        //先清空模板工程
        boolean delResult = FileUtils.deleteAllInDir(skinResPath);
        getUtilConfigProvider().onLog("清空模板工程资源 " + (delResult ? "完成" : "失败"));
        if (!delResult) return false;
        //清除皮肤包
        boolean delSkinResult = FileUtils.deleteAllInDir(getUtilConfigProvider().getSkinProjectPath() + "\\app\\build");
        getUtilConfigProvider().onLog("清空输出目录 " + (delSkinResult ? "完成" : "失败"));
        if (!delSkinResult) return false;
        //复制皮肤资源到打包工程
        boolean copyResult = FileUtils.copy(originResPath, skinResPath);
        getUtilConfigProvider().onLog("复制资源到模板工程 " + (copyResult ? "完成" : "失败"));
        if (!copyResult) return false;
        //删除原本的Manifest文件
        FileUtils.delete(getAndroidManifestFilePath());
        //生成Manifest文件
        //生成推送命令,打包命令
        boolean createFileResult = createFile();
        getUtilConfigProvider().onLog("------资源准备阶段结束------");
        return createFileResult;
    }

    private String getAndroidManifestFilePath() {
        return getUtilConfigProvider().getSkinProjectPath() + "\\app\\src\\main\\AndroidManifest.xml";
    }

    /**
     * 生成皮肤工程的打包命令
     *
     * @return
     */
    private boolean createFile() {

        File androidManifest = new File(getAndroidManifestFilePath());
        if (!androidManifest.exists()) {
            try {
                androidManifest.createNewFile();
                //写命令进入
                PrintWriter printWriter = new PrintWriter(androidManifest);
                printWriter.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
                printWriter.append("\n");
                printWriter.append("<manifest />");
                printWriter.flush();
                printWriter.close();
                getUtilConfigProvider().onLog("创建AndroidManifest.xml 完成");
            } catch (IOException e) {
                getUtilConfigProvider().onLog(e.getMessage());
                getUtilConfigProvider().onLog("创建AndroidManifest.xml 失败");
                return false;
            }
        }

        //修改build.gradle中的命名空间
        fixNameSpace();

        File rootFile = new File(getCacheDirPath() + "\\root.cmd");
        if (!rootFile.exists()) {
            try {
                rootFile.createNewFile();
                //写命令进入
                PrintWriter printWriter = new PrintWriter(rootFile);
                printWriter.append("adb root");
                printWriter.append("\n");
                printWriter.append("adb remount");
                printWriter.flush();
                printWriter.close();
            } catch (IOException e) {
                getUtilConfigProvider().onLog(e.getMessage());
                return false;
            }
        }
        File file = new File(getUtilConfigProvider().getSkinProjectPath() + "\\assembleRelease.cmd");
        //写入内容 cd
        if (!file.exists()) {
            //在皮肤工程下创建 assembleRelease.cmd 文件
            boolean cmdFileCreateSuccess = FileUtils.createFileByDeleteOldFile(getUtilConfigProvider().getSkinProjectPath() + "\\assembleRelease.cmd");
            if (!cmdFileCreateSuccess) return false;
            try {
                PrintWriter printWriter = new PrintWriter(file);
                printWriter.append("C:");
                printWriter.append("\n");
                printWriter.append("cd ");
                printWriter.append(getUtilConfigProvider().getSkinProjectPath());
                printWriter.append("\n");
                printWriter.append("./gradlew assembleRelease");
                printWriter.flush();
                printWriter.close();
            } catch (IOException e) {
                getUtilConfigProvider().onLog(e.getMessage());
                return false;
            }
        }

        return true;
    }

    private boolean fixNameSpace() {
        File originBuildFile = new File(getUtilConfigProvider().getSkinProjectPath() + "\\app\\build.gradle");
        if (originBuildFile.exists()) {
            try {
                BufferedReader bufferedReader = new BufferedReader(new FileReader(originBuildFile));


                //逐行读取内容
                String line;
                ArrayList<String> content = new ArrayList<>();
                while ((line = bufferedReader.readLine()) != null) { // 逐行读取输出结果
                    //匹配到命名空间的那一行时替换内容
                    if (line.contains("namespace =")) {
                        String nameSpace = "    namespace = '" + getUtilConfigProvider().getProject().getPackageName() + "'";
                        content.add(nameSpace);
                    } else {
                        content.add(line);
                    }
                }
                bufferedReader.close();
                //把数据写回去
                //将修改后的内容重新写入到文件
                BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(originBuildFile, StandardCharsets.UTF_8));
                for (int i = 0; i < content.size(); i++) {
                    bufferedWriter.append(content.get(i));
                    //最后一行不新增空格
                    if (i != content.size() - 1) {
                        bufferedWriter.newLine();
                    }
                }
                bufferedWriter.flush();
                bufferedReader.close();
            } catch (Exception e) {
                return false;
            }
        }
        return true;
    }

    private boolean isEnableOption(int option) {
        return (getUtilConfigProvider().launchType() & option) != 0;
    }

    /**
     * 皮肤包制作完成之后的收尾工作
     */
    public void onAfterMakeSkin() throws IOException {
        getUtilConfigProvider().onLoadingStart();
        String outFileDir = getUtilConfigProvider().getSkinProjectPath() + "\\app\\build\\outputs\\apk\\release\\";
        String skinFileName = getUtilConfigProvider().getProject().getSkinFileName();

        if (isEnableOption(TYPE_OPEN_EXPLORE)) {
            getUtilConfigProvider().onLog("打开目录 " + outFileDir);
            //打开对应的输出目录
            Runtime.getRuntime().exec("explorer " + outFileDir);
            getUtilConfigProvider().onLoadingEnd();
        }

        String packageName = getUtilConfigProvider().getProject().getPackageName();
        String tag = packageName.substring(packageName.lastIndexOf('.') + 1);

        if (isEnableOption(TYPE_REPLACE_TO_GIT)) {

            if (getUtilConfigProvider().getProject().getGitProjectPath() == null || getUtilConfigProvider().getProject().getGitProjectPath().isEmpty()) {
                getUtilConfigProvider().onLog(" " + getUtilConfigProvider().getProject().getProjectName() + " 未配置Git仓库根目录");
                getUtilConfigProvider().onLoadingEnd();
                return;
            }
            if (getUtilConfigProvider().getProject().getPackageName() == null || getUtilConfigProvider().getProject().getPackageName().isEmpty()) {
                getUtilConfigProvider().onLog(" " + getUtilConfigProvider().getProject().getProjectName() + " 未配置应用包名");
                getUtilConfigProvider().onLoadingEnd();
                return;
            }
            if (getUtilConfigProvider().getProject().getBranchName() == null || getUtilConfigProvider().getProject().getBranchName().isEmpty()) {
                getUtilConfigProvider().onLog(" " + getUtilConfigProvider().getProject().getProjectName() + " 未配置Git分支名称");
                getUtilConfigProvider().onLoadingEnd();
                return;
            }

            GitUtils.getInstance().setUtilConfigProvider(getUtilConfigProvider());
            //如果没有配置Git上传目录则跳过
            getUtilConfigProvider().onLog("------ Git ------");
            //还原对应包名目录中的修改
            GitUtils.getInstance().restoreUncommittedChanges();
            //清理对应包名目录,移除未版本控制的文件
            GitUtils.getInstance().cleanWorkingDirectory();
            //从服务器拉取最新内容
            GitUtils.getInstance().pull();
            //切换分支
            GitUtils.getInstance().switchBranch();
            //替换皮肤包到对应包名目录下
            String gitPath = getUtilConfigProvider().getProject().getGitProjectPath() + "\\daytime_mode\\" + packageName;
            boolean copy = FileUtils.copy(outFileDir + "/" + skinFileName, gitPath + "/" + skinFileName);
            getUtilConfigProvider().onLog("替换到仓库目录" + (copy ? "完成" : "失败"));
            //执行git add .
            GitUtils.getInstance().addSkinFile();
            //执行git commit
            GitUtils.getInstance().commit(tag);
            //执行上传命令
            GitUtils.getInstance().push();
            //打开目录手动提交
            //打开git目录
//            getUtilConfigProvider().onLog("打开目录 " + gitPath);
//            Runtime.getRuntime().exec("explorer " + gitPath);
        }


        if (isEnableOption(TYPE_PUSH_TO_DEVICE)) {
            if (getUtilConfigProvider().getProject().getPackageName() == null || getUtilConfigProvider().getProject().getPackageName().isEmpty()) {
                getUtilConfigProvider().onLog(" " + getUtilConfigProvider().getProject().getProjectName() + " 未配置应用包名");
                getUtilConfigProvider().onLoadingEnd();
                return;
            }
            //推送到设备
            String command = getCacheDirPath() + "\\root.cmd"; // 要执行的命令
            Process process = Runtime.getRuntime().exec(command);// 执行命令

            try {
                int resultCode = process.waitFor();
                if (resultCode != 0) {
                    getUtilConfigProvider().onLog("root失败");
                    getUtilConfigProvider().onLoadingEnd();
                    return;
                }
            } catch (InterruptedException e) {
                getUtilConfigProvider().onLog(e.getMessage());
                getUtilConfigProvider().onLoadingEnd();
            }


            getUtilConfigProvider().onLog("adb push " + outFileDir + skinFileName + " /system/media/bwskin/" + getUtilConfigProvider().getProject().getDeviceSkinFolderName() + "/" + packageName + "/" + skinFileName);
            Process exec = Runtime.getRuntime().exec("adb push " + outFileDir + skinFileName + " /system/media/bwskin/" + getUtilConfigProvider().getProject().getDeviceSkinFolderName() + "/" + packageName + "/" + skinFileName);

            try {
                int resultCode = exec.waitFor();
                if (resultCode != 0) {
                    getUtilConfigProvider().onLog("推送皮肤包到设备失败");
                    getUtilConfigProvider().onLoadingEnd();
                    return;
                }
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            getUtilConfigProvider().onLog("推送皮肤包到设备成功");

            //重启应用
            Runtime.getRuntime().exec("adb shell sync");
            Runtime.getRuntime().exec("adb shell pkill " + tag);
            getUtilConfigProvider().onLog("重启应用 " + packageName);
            try {
                Runtime.getRuntime().exec("adb shell monkey -p " + getUtilConfigProvider().getProject().getPackageName() + " -c android.intent.category.LAUNCHER 1");
                getUtilConfigProvider().onLoadingEnd();
            } catch (IOException e) {
                e.printStackTrace();
                getUtilConfigProvider().onLog(e.getMessage());
                getUtilConfigProvider().onLoadingEnd();
            }
        }
    }


    private UtilConfigProvider getUtilConfigProvider() {
        return utilConfigProvider;
    }


    public interface UtilConfigProvider {
        /**
         * 获取皮肤工程所在路径
         *
         * @return
         */
        String getSkinProjectPath();

        /**
         * 选择的项目
         */
        ProjectConfigEntity getProject();

        /**
         * 启动类型
         * 0:完成后打开所在目录
         * 1:完成后推送到设备
         * 2:完成后替换到Git上传路径
         */
        int launchType();


        void onLog(String msg);

        /**
         * 皮肤包制作成功
         */
        void onCreateSkinFileSuccess();

        void onLoadingStart();

        void onLoadingEnd();
    }

}
